使用 beeline 和 hiveserver2 连接 在一个窗口中使用 hiveserver2,让窗口一直不关闭,在另一个窗口进入 beeline 后使用 JDBC 进行连接,使用 beeline 的好处是查询结果格式以更方便的形式的显示
常用函数 nvl NVL( string1, replace_with): 判断 string1 是否为null,如果为null,使用 replace_with 替换null,否则就返回 string1
1 select avg (nvl(comm, 0 )) from emp1;
例如上述例子中,对 comm 列计算平均值,如果 comm 为 null,则使用 0 代替。如果这里不使用 nvl 函数的话,那么计算平均值是不算上 null 的个数的,数据如下所示,不使用 nvl ,平均值为 (300+500+1400+0)/ 4 = 550。使用 nvl 平均值就是 146.66666666666666
concat 字符串拼接。 可以在参数中传入多个 string 类型的字符串,但是一旦有一个参数为 null,则返回 null
1 2 select concat ("a" ,"v" ); select concat ("a" ,"v" ,null );
concat_ws 使用指定的分隔符完成字符串拼接,格式为 concat_ws(分隔符,[string | array<string>]+)
,第一个参数为分隔符,后面为要拼接的字符串或者数组。
1 select concat_ws ("." ,"zhansan" ,array ("lisi" ,"wangwu" ));
collect_set collect_set(列名)
作用是将此列的多行记录合并为一个 set 集合,去重
collect_list collect_list(列名)
作用是将此列的多行记录合并为一个 set 集合,不去重
explode explode(列名)
参数只能是 array 或 map, 将 array 类型参数转为1列N行, 将 map 类型参数转为2列N行
练习 练习一 有以下数据,求出不同部门男女各多少人
期望查询结果如下
方法1,按照部门分组,单独查询出男女的个数,然后在将结果进行汇总。下面方式 HQL 性能不高,有两个字查询,一个汇总,所以需要三个 job 才能运行完成。
1 2 3 4 5 select a.dept_id, male_count, female_count from (select dept_id, count (1 ) male_count from emp_sex where sex="男" group by dept_id) a join (select dept_id, count (1 ) female_count from emp_sex where sex="女" group by dept_id) b on a.dept_id = b.dept_id;
方法2,利用 sum 函数,在求男性总人数时,如果当前人的性别为男,记1,否则记 0,sum 该字段就得到了男性的值。在求女性总人数时,如果当前人的性别为女,记1,否则记0,sum 该字段就得到了男性的值。
case when 的语法如下,这一列中出现的 值1
会被替换为 值2
, 值3
会被替换为 值4
, 其他的替换为值5
1 2 3 4 5 6 case 列名 when 值1 then 值2 when 值3 then 值4 ... else 值5 end
1 2 3 4 select dept_id,sum (case sex when "男" then 1 else 0 end ) male_count,sum (case sex when "女" then 1 else 0 end ) female_countfrom emp_sex group by dept_id;
使用 case when 的优化 HQL 如上,只需要一个 job 就能完成。
HQL 中除了 case when 能做判断外,if 也能做判断,语法为 if(判断表达式,值1,值2)
,值1当表达式为 true 时获取,值2当表达式为 false 时获取。实现 HQL 如下:
1 2 3 4 select dept_id,sum (if (sex == "男" , 1 , 0 )) male_count,sum (if (sex == "女" , 1 , 0 )) female_countfrom emp_sex group by dept_id;
这个 HQL 也是只需要一个 job 就能完成。
练习二
把星座和血型一样的人归类到一起。结果如下:
1 2 3 射手座,A 大海|凤姐 白羊座,A 孙悟空|猪八戒 白羊座,B 宋宋
这里需要使用函数 concat_ws 进行字符串的拼接,还需要使用 collect_list 将某列的多行记录合并为一个 list 集合,不去重。
1 2 3 select concat (constellation,',' ,blood_type),concat_ws ('|' ,collect_list(name ))from person_infogroup by constellation,blood_type
练习三
将电影分类中的数组数据展开。结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 《疑犯追踪》 悬疑 《疑犯追踪》 动作 《疑犯追踪》 科幻 《疑犯追踪》 剧情 《Lie to me》 悬疑 《Lie to me》 警匪 《Lie to me》 动作 《Lie to me》 心理 《Lie to me》 剧情 《战狼2》 战争 《战狼2》 动作 《战狼2》 灾难
将 category 列进行 explode,即转换为 1列N行1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 0: jdbc:hive2://hadoop10:10000> select explode(category) from movie_info; + | col | + | 悬疑 | | 动作 | | 科幻 | | 剧情 | | 悬疑 | | 警匪 | | 动作 | | 心理 | | 剧情 | | 战争 | | 动作 | | 灾难 | +
1 2 select movie,col1from movie_info lateral view explode (category ) tmp1 as col1
lateral view 的作用是将炸裂后的1列N行,在逻辑上依然视作1列1行,实际是1列N行,然后查询时和movie进行笛卡尔集这个操作在hive中称为侧写(lateral view)
练习四 有以下数据
1 2 3 person_info2.names person_info2.tags person_info2.hobbys ["jack","tom","jerry"] ["阳光男孩","肌肉男孩","直男"] ["晒太阳","健身","说多喝热水"] ["marry","nancy"] ["阳光女孩","肌肉女孩","腐女"] ["晒太阳","健身","看有内涵的段子"]
希望得到以下查询结果
1 2 3 4 5 6 7 8 期望结果: jack 阳光男孩 晒太阳 jack 阳光男孩 健身 jack 阳光男孩 说多喝热水 jack 肌肉男孩 晒太阳 jack 肌肉男孩 健身 jack 肌肉男孩 说多喝热水 .....
查询 SQL
1 2 3 4 5 select name ,tag,hobbyfrom person_info2lateral view explode (names ) tmp1 as name lateral view explode (tags) tmp1 as taglateral view explode (hobbys) tmp1 as hobby;
窗口函数 即可以在函数在运行时通过改变窗口的大小,来控制计算的数据集的范围。
文档地址 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics
常用函数 窗口函数有以下三类
第一类
1 2 3 4 5 6 7 LEAD: LEAD (scalar_expression [,offset] [,default]): 返回当前行以下N行的指定列的列值,如果找不到,就采用默认值 LAG: LAG (scalar_expression [,offset] [,default]): 返回当前行以上N行的指定列的列值,如果找不到,就采用默认值 FIRST_VALUE: FIRST_VALUE(列名,[false(默认)]): 返回当前窗口指定列的第一个值,第二个参数如果为true,代表加入第一个值为null,跳过空值,继续寻找! LAST_VALUE: LAST_VALUE(列名,[false(默认)]): 返回当前窗口指定列的最后一个值,第二个参数如果为true,代表加入第一个值为null,跳过空值,继续寻找!
第二类1 统计类的函数(一般都需要结合over使用): min,max,avg,sum,count
第三类1 排名分析函数:RANK,ROW_NUMBER,DENSE_RANK,CUME_DIST,PERCENT_RANK,NTILE
语法 相关语法解释
1 2 3 4 5 6 7 8 OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化 CURRENT ROW:当前行 n PRECEDING:往前n行数据 n FOLLOWING:往后n行数据 UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点 LAG(col,n):往前第n行数据 LEAD(col,n):往后第n行数据 NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。
窗口函数的使用格式为 函数 over( partition by 字段 ,order by 字段 window_clause )
window_clause 为窗口的大小,窗口大小常用格式如下
1 2 3 4 5 (rows | range) between (unbounded | [num]) preceding and ([num] preceding | current row | (unbounded | [num]) following) (rows | range) between current row and (current row | (unbounded | [num]) following) (rows | range) between [num] following and (unbounded | [num]) following
特殊情况:
在 over() 中既没有出现 windows_clause,也没有出现 order by,窗口默认为 rows between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING
在over()中没有出现 windows_clause,但指定了 order by,窗口默认为 rows between UNBOUNDED PRECEDING and CURRENT ROW
窗口函数和分组有什么区别:
如果是分组操作,select 后只能写分组后的字段
如果是窗口函数,窗口函数是在指定的窗口内,对每条记录都执行一次函数
如果是分组操作,有去重效果,而窗口函数中的 partition不去重
注意⚠️:不是所有的函数在运行都是可以通过改变窗口的大小,来控制计算的数据集的范围,所有的排名函数和LAG,LEAD,支持使用 over(),但是在 over() 中不能定义 window_clause。
查询示例 例如有以下数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 0: jdbc:hive2://hadoop10:10000> select * from business; +----------------+---------------------+----------------+--+ | business.name | business.orderdate | business.cost | +----------------+---------------------+----------------+--+ | jack | 2017-01-01 | 10 | | tony | 2017-01-02 | 15 | | jack | 2017-02-03 | 23 | | tony | 2017-01-04 | 29 | | jack | 2017-01-05 | 46 | | jack | 2017-04-06 | 42 | | tony | 2017-01-07 | 50 | | jack | 2017-01-08 | 55 | | mart | 2017-04-08 | 62 | | mart | 2017-04-09 | 68 | | neil | 2017-05-10 | 12 | | mart | 2017-04-11 | 75 | | neil | 2017-06-12 | 80 | | mart | 2017-04-13 | 94 | +----------------+---------------------+----------------+--+
需要进行以下查询
(1)查询在2017年4月份购买过的顾客及总人数
1 2 3 4 select name ,count (*) over (rows between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING )from businesswhere substring (orderdate,1 ,7 )='2017-04' group by name
上面的写法等价于
1 2 3 4 select name ,count (*) over ()from businesswhere substring (orderdate,1 ,7 )='2017-04' group by name
查询结果为
1 2 3 4 5 6 +-------+-----------------+--+ | name | count_window_0 | +-------+-----------------+--+ | mart | 2 | | jack | 2 | +-------+-----------------+--+
(2)查询顾客的购买明细及月购买总额
1 2 select name ,orderdate,cost ,sum (cost ) over (partition by name ,substring (orderdate,1 ,7 ) ) from business
查询 name, orderdate, cost,并对 cost 进行按月份的累加求和, 结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+---------------+--+ | name | orderdate | cost | sum_window_0 | +-------+-------------+-------+---------------+--+ | jack | 2017-01-05 | 46 | 111 | | jack | 2017-01-08 | 55 | 111 | | jack | 2017-01-01 | 10 | 111 | | jack | 2017-02-03 | 23 | 23 | | jack | 2017-04-06 | 42 | 42 | | mart | 2017-04-13 | 94 | 299 | | mart | 2017-04-11 | 75 | 299 | | mart | 2017-04-09 | 68 | 299 | | mart | 2017-04-08 | 62 | 299 | | neil | 2017-05-10 | 12 | 12 | | neil | 2017-06-12 | 80 | 80 | | tony | 2017-01-04 | 29 | 94 | | tony | 2017-01-02 | 15 | 94 | | tony | 2017-01-07 | 50 | 94 | +-------+-------------+-------+---------------+--+
(3)查询顾客的购买明细, 并将cost按照日期进行累加
1 2 select name ,orderdate,cost ,sum (cost ) over (partition by name order by orderdate ) from business
查询 name, orderdate, cost,并对 cost 进行按名称的累加,结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+---------------+--+ | name | orderdate | cost | sum_window_0 | +-------+-------------+-------+---------------+--+ | jack | 2017-01-01 | 10 | 10 | | jack | 2017-01-05 | 46 | 56 | | jack | 2017-01-08 | 55 | 111 | | jack | 2017-02-03 | 23 | 134 | | jack | 2017-04-06 | 42 | 176 | | mart | 2017-04-08 | 62 | 62 | | mart | 2017-04-09 | 68 | 130 | | mart | 2017-04-11 | 75 | 205 | | mart | 2017-04-13 | 94 | 299 | | neil | 2017-05-10 | 12 | 12 | | neil | 2017-06-12 | 80 | 92 | | tony | 2017-01-02 | 15 | 15 | | tony | 2017-01-04 | 29 | 44 | | tony | 2017-01-07 | 50 | 94 | +-------+-------------+-------+---------------+--+
(4)查询顾客的购买明细及顾客上次的购买时间
1 select name ,orderdate,cost ,lag(orderdate,1 ,'无数据' ) over (partition by name order by orderdate) from business
LAG(col,n) 表示取之前的第n行的 col 列的数据
上面查询代表查询 name,orderdate,cost 信息,并且取 orderdate 的上一条数据,如果没数据就显示 “无数据”,并按 name 分组,orderdate 排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+---------------+--+ | name | orderdate | cost | lag_window_0 | +-------+-------------+-------+---------------+--+ | jack | 2017-01-01 | 10 | 无数据 | | jack | 2017-01-05 | 46 | 2017-01-01 | | jack | 2017-01-08 | 55 | 2017-01-05 | | jack | 2017-02-03 | 23 | 2017-01-08 | | jack | 2017-04-06 | 42 | 2017-02-03 | | mart | 2017-04-08 | 62 | 无数据 | | mart | 2017-04-09 | 68 | 2017-04-08 | | mart | 2017-04-11 | 75 | 2017-04-09 | | mart | 2017-04-13 | 94 | 2017-04-11 | | neil | 2017-05-10 | 12 | 无数据 | | neil | 2017-06-12 | 80 | 2017-05-10 | | tony | 2017-01-02 | 15 | 无数据 | | tony | 2017-01-04 | 29 | 2017-01-02 | | tony | 2017-01-07 | 50 | 2017-01-04 | +-------+-------------+-------+---------------+--+
(5)查询顾客的购买明细及顾客下次的购买时间
和上面差不多,只不过需要将函数 lag 换为 lead
1 select name ,orderdate,cost ,lead (orderdate,1 ,'无数据' ) over (partition by name order by orderdate ) from business
结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+----------------+--+ | name | orderdate | cost | lead_window_0 | +-------+-------------+-------+----------------+--+ | jack | 2017-01-01 | 10 | 2017-01-05 | | jack | 2017-01-05 | 46 | 2017-01-08 | | jack | 2017-01-08 | 55 | 2017-02-03 | | jack | 2017-02-03 | 23 | 2017-04-06 | | jack | 2017-04-06 | 42 | 无数据 | | mart | 2017-04-08 | 62 | 2017-04-09 | | mart | 2017-04-09 | 68 | 2017-04-11 | | mart | 2017-04-11 | 75 | 2017-04-13 | | mart | 2017-04-13 | 94 | 无数据 | | neil | 2017-05-10 | 12 | 2017-06-12 | | neil | 2017-06-12 | 80 | 无数据 | | tony | 2017-01-02 | 15 | 2017-01-04 | | tony | 2017-01-04 | 29 | 2017-01-07 | | tony | 2017-01-07 | 50 | 无数据 | +-------+-------------+-------+----------------+--+
(6)查询顾客的购买明细及顾客本月第一次购买的时间
第一次购买的时间只需要按照购买时间拍正序,然后取第一条记录即可,这里使用函数 FIRST_VALUE 取第一条记录。
1 select name ,orderdate,cost ,FIRST_VALUE (orderdate,true ) over (partition by name ,substring (orderdate,1 ,7 ) order by orderdate ) from business
查询结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+-----------------------+--+ | name | orderdate | cost | first_value_window_0 | +-------+-------------+-------+-----------------------+--+ | jack | 2017-01-01 | 10 | 2017-01-01 | | jack | 2017-01-05 | 46 | 2017-01-01 | | jack | 2017-01-08 | 55 | 2017-01-01 | | jack | 2017-02-03 | 23 | 2017-02-03 | | jack | 2017-04-06 | 42 | 2017-04-06 | | mart | 2017-04-08 | 62 | 2017-04-08 | | mart | 2017-04-09 | 68 | 2017-04-08 | | mart | 2017-04-11 | 75 | 2017-04-08 | | mart | 2017-04-13 | 94 | 2017-04-08 | | neil | 2017-05-10 | 12 | 2017-05-10 | | neil | 2017-06-12 | 80 | 2017-06-12 | | tony | 2017-01-02 | 15 | 2017-01-02 | | tony | 2017-01-04 | 29 | 2017-01-02 | | tony | 2017-01-07 | 50 | 2017-01-02 | +-------+-------------+-------+-----------------------+--+
(7)查询顾客的购买明细及顾客本月最后一次购买的时间
和上面类似,只是使用函数不同, 因为是取本月最后一次购买的时间,所以这里要限制窗口的位置,窗口的位置就是当前行到本次分组的最后一行。
1 select name ,orderdate,cost ,LAST_VALUE (orderdate,true ) over (partition by name ,substring (orderdate,1 ,7 ) order by orderdate rows between CURRENT row and UNBOUNDED FOLLOWING ) from business
查询结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+----------------------+--+ | name | orderdate | cost | last_value_window_0 | +-------+-------------+-------+----------------------+--+ | jack | 2017-01-01 | 10 | 2017-01-08 | | jack | 2017-01-05 | 46 | 2017-01-08 | | jack | 2017-01-08 | 55 | 2017-01-08 | | jack | 2017-02-03 | 23 | 2017-02-03 | | jack | 2017-04-06 | 42 | 2017-04-06 | | mart | 2017-04-08 | 62 | 2017-04-13 | | mart | 2017-04-09 | 68 | 2017-04-13 | | mart | 2017-04-11 | 75 | 2017-04-13 | | mart | 2017-04-13 | 94 | 2017-04-13 | | neil | 2017-05-10 | 12 | 2017-05-10 | | neil | 2017-06-12 | 80 | 2017-06-12 | | tony | 2017-01-02 | 15 | 2017-01-07 | | tony | 2017-01-04 | 29 | 2017-01-07 | | tony | 2017-01-07 | 50 | 2017-01-07 | +-------+-------------+-------+----------------------+--+
(8)查询顾客的购买明细及顾客最近三次cost花费
最近三次可以是 当前和之前两次 或 当前+前一次+后一次
当前和之前两次:
1 select name ,orderdate,cost ,sum (cost ) over (partition by name order by orderdate rows between 2 PRECEDING and CURRENT row ) from business
当前+前一次+后一次:
1 select name ,orderdate,cost ,sum (cost ) over (partition by name order by orderdate rows between 1 PRECEDING and 1 FOLLOWING ) from business
查询结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +-------+-------------+-------+---------------+--+ | name | orderdate | cost | sum_window_0 | +-------+-------------+-------+---------------+--+ | jack | 2017-01-01 | 10 | 56 | | jack | 2017-01-05 | 46 | 111 | | jack | 2017-01-08 | 55 | 124 | | jack | 2017-02-03 | 23 | 120 | | jack | 2017-04-06 | 42 | 65 | | mart | 2017-04-08 | 62 | 130 | | mart | 2017-04-09 | 68 | 205 | | mart | 2017-04-11 | 75 | 237 | | mart | 2017-04-13 | 94 | 169 | | neil | 2017-05-10 | 12 | 92 | | neil | 2017-06-12 | 80 | 92 | | tony | 2017-01-02 | 15 | 44 | | tony | 2017-01-04 | 29 | 94 | | tony | 2017-01-07 | 50 | 79 | +-------+-------------+-------+---------------+--+
(9)查询前20%时间的订单信息
排名函数 1 2 3 4 5 6 RANK: 允许并列,一旦有并列跳号! ROW_NUMBER: 行号! 连续的,每个号之间差1! DENSE_RANK: 允许并列,一旦有并列不跳号! CUME_DIST: 从排序后的第一行到当前值之间数据 占整个数据集的百分比! PERCENT_RANK: rank-1/ 总数据量-1 NTILE(x): 将数据集均分到X个组中,返回每条记录所在的组号
示例数据如下1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +-------------+----------------+--------------+--+ | score.name | score.subject | score.score | +-------------+----------------+--------------+--+ | 孙悟空 | 语文 | 87 | | 孙悟空 | 数学 | 95 | | 孙悟空 | 英语 | 68 | | 大海 | 语文 | 94 | | 大海 | 数学 | 56 | | 大海 | 英语 | 84 | | 宋宋 | 语文 | 64 | | 宋宋 | 数学 | 86 | | 宋宋 | 英语 | 84 | | 婷婷 | 语文 | 65 | | 婷婷 | 数学 | 85 | | 婷婷 | 英语 | 78 | +-------------+----------------+--------------+--+
查询示例如下1 2 3 4 5 6 select *,rank () over (order by score) ranknum,ROW_NUMBER() over (order by score) rnnum, DENSE_RANK () over (order by score) drnum,CUME_DIST () over (order by score) cdnum,PERCENT_RANK () over (order by score) prnumfrom score;
查询结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 score.name score.subject score.score ranknum rnnum drnum cdnum prnum 大海 数学 56 1 1 1 0.08333333333333333 0.0 宋宋 语文 64 2 2 2 0.16666666666666666 0.09090909090909091 婷婷 语文 65 3 3 3 0.25 0.18181818181818182 孙悟空 英语 68 4 4 4 0.3333333333333333 0.2727272727272727 婷婷 英语 78 5 5 5 0.4166666666666667 0.36363636363636365 宋宋 英语 84 6 6 6 0.5833333333333334 0.45454545454545453 大海 英语 84 6 7 6 0.5833333333333334 0.45454545454545453 婷婷 数学 85 8 8 7 0.6666666666666666 0.6363636363636364 宋宋 数学 86 9 9 8 0.75 0.7272727272727273 孙悟空 语文 87 10 10 9 0.8333333333333334 0.8181818181818182 大海 语文 94 11 11 10 0.9166666666666666 0.9090909090909091 孙悟空 数学 95 12 12 11 1.0 1.0 Time taken: 38.666 seconds, Fetched: 12 row(s)
查询示例 (1) 按照科目进行排名
1 select *,rank () over (partition by subject order by score desc ) from score
查询结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +-------------+----------------+--------------+----------------+--+ | score.name | score.subject | score.score | rank_window_0 | +-------------+----------------+--------------+----------------+--+ | 孙悟空 | 数学 | 95 | 1 | | 宋宋 | 数学 | 86 | 2 | | 婷婷 | 数学 | 85 | 3 | | 大海 | 数学 | 56 | 4 | | 宋宋 | 英语 | 84 | 1 | | 大海 | 英语 | 84 | 1 | | 婷婷 | 英语 | 78 | 3 | | 孙悟空 | 英语 | 68 | 4 | | 大海 | 语文 | 94 | 1 | | 孙悟空 | 语文 | 87 | 2 | | 婷婷 | 语文 | 65 | 3 | | 宋宋 | 语文 | 64 | 4 | +-------------+----------------+--------------+----------------+--+
(2)给每个学生的总分进行排名
1 2 3 4 5 select name ,sumscore,rank () over ( order by sumscore desc )from (select name ,sum (score) sumscore from scoregroup by name ) tmp
1 2 3 4 5 6 7 8 +-------+-----------+----------------+--+ | name | sumscore | rank_window_0 | +-------+-----------+----------------+--+ | 孙悟空 | 250 | 1 | | 宋宋 | 234 | 2 | | 大海 | 234 | 2 | | 婷婷 | 228 | 4 | +-------+-----------+----------------+--+
(3)求每个学生的成绩明细及给每个学生的总分和总分排名
1 2 3 4 select *,DENSE_RANK () over (order by tmp.sumscore desc )from (select *,sum (score) over (partition by name ) sumscore from score) tmp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +-----------+--------------+------------+---------------+----------------------+--+ | tmp.name | tmp.subject | tmp.score | tmp.sumscore | dense_rank_window_0 | +-----------+--------------+------------+---------------+----------------------+--+ | 孙悟空 | 语文 | 87 | 250 | 1 | | 孙悟空 | 数学 | 95 | 250 | 1 | | 孙悟空 | 英语 | 68 | 250 | 1 | | 宋宋 | 语文 | 64 | 234 | 2 | | 宋宋 | 数学 | 86 | 234 | 2 | | 宋宋 | 英语 | 84 | 234 | 2 | | 大海 | 语文 | 94 | 234 | 2 | | 大海 | 数学 | 56 | 234 | 2 | | 大海 | 英语 | 84 | 234 | 2 | | 婷婷 | 语文 | 65 | 228 | 3 | | 婷婷 | 数学 | 85 | 228 | 3 | | 婷婷 | 英语 | 78 | 228 | 3 | +-----------+--------------+------------+---------------+----------------------+--+
(4)只查询每个科目的成绩的前2名
1 2 3 4 5 select *from (select *,rank () over (partition by subject order by score desc ) rn from score) tmpwhere rn<=2
1 2 3 4 5 6 7 8 9 10 +-----------+--------------+------------+---------+--+ | tmp.name | tmp.subject | tmp.score | tmp.rn | +-----------+--------------+------------+---------+--+ | 孙悟空 | 数学 | 95 | 1 | | 宋宋 | 数学 | 86 | 2 | | 宋宋 | 英语 | 84 | 1 | | 大海 | 英语 | 84 | 1 | | 大海 | 语文 | 94 | 1 | | 孙悟空 | 语文 | 87 | 2 | +-----------+--------------+------------+---------+--+
(5)查询学生成绩明细,并显示当前科目最高分
1 2 select *,max (score) over (partition by subject)from score
或者
1 2 select *,FIRST_VALUE (score) over (partition by subject order by score desc )from score
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +-------------+----------------+--------------+---------------+--+ | score.name | score.subject | score.score | max_window_0 | +-------------+----------------+--------------+---------------+--+ | 婷婷 | 数学 | 85 | 95 | | 宋宋 | 数学 | 86 | 95 | | 大海 | 数学 | 56 | 95 | | 孙悟空 | 数学 | 95 | 95 | | 婷婷 | 英语 | 78 | 84 | | 宋宋 | 英语 | 84 | 84 | | 大海 | 英语 | 84 | 84 | | 孙悟空 | 英语 | 68 | 84 | | 婷婷 | 语文 | 65 | 94 | | 宋宋 | 语文 | 64 | 94 | | 大海 | 语文 | 94 | 94 | | 孙悟空 | 语文 | 87 | 94 | +-------------+----------------+--------------+---------------+--+